/**
 * 全屏键盘
 * 组件: 左侧大键盘, 右侧[数字键盘,触摸板]
 *
 * @author hugan
 * @date 2023/11/8
 */
import "../common/plugins/vue/2.6.11.min.js"
import browserUtil from "../common/util/browserUtil.js"
import storageUtil from "../common/util/storageUtil.js"

let component = {
  template: `<div h-keyboard>
<!--实际旋转的对象: [h-keyboard, setting-dialog-content]-->
<div id="h-keyboard" style="height: 100vh; display: flex; justify-content: center; align-items: center;">
  <!--主键盘-->
  <div id="main-board" class="key-bg">
    <div class="key-row">
        <span class="btnWidth-x1"></span>
        <button keyCode="SPECIAL:0xB3" class="mediaButton">▶/║</button>
        <button keyCode="SPECIAL:0xB1" class="mediaButton">┃◀◀</button>
        <button keyCode="SPECIAL:0xB0" class="mediaButton">▶▶┃</button>
        <span class="btnWidth-x1"></span>
        <button keyCode="0x24">Home</button>
        <button keycode="0x23">End</button>
        <button keyCode="0x21">Pg▲</button>
        <button keycode="0x22">Pg▼</button>
        <span class="btnWidth-x0d6"></span>
    
        <div class="lamp-board btnWidth-x2d6">
          <div class="lamp-row" style="align-items: end">
            <span :class="wsConnected?'lamp-on':'lamp-off'">◉</span>
            <span keyCode="0x90" updateKeyboardState style="cursor: pointer" :class="numOn?'lamp-on':'lamp-off'">◉</span>
            <span keyCode="0x14" updateKeyboardState style="cursor: pointer" :class="capOn?'lamp-on':'lamp-off'">◉</span>
            <span keyCode="0x91" updateKeyboardState style="cursor: pointer" :class="scrollOn?'lamp-on':'lamp-off'">◉</span>
          </div>
          <div class="lamp-row" style="align-items: baseline">
            <span>连接</span>
            <span keyCode="0x90" updateKeyboardState style="cursor: pointer">①</span>
            <span keyCode="0x14" updateKeyboardState style="cursor: pointer">Ⓐ</span>
            <span keyCode="0x91" updateKeyboardState style="cursor: pointer">Ⓢ</span>  
          </div>
        </div>
        <span class="btnWidth-x0d6"></span>
    
        <button id="btnSetting" @click="showSetting()">❖</button>
        <button @click="switchMode()">Mode</button>
    </div>
    <!---->
    <div class="key-row">
      <button keyCode="0x1B">Esc</button>
      <span class="btnWidth-x0d6"></span>
      <button keyCode="0x70">F1</button>
      <button keyCode="0x71">F2</button>
      <button keyCode="0x72">F3</button>
      <button keyCode="0x73">F4</button>
      <span class="btnWidth-x0d6"></span>
      <button keyCode="0x74">F5</button>
      <button keyCode="0x75">F6</button>
      <button keyCode="0x76">F7</button>
      <button keyCode="0x77">F8</button>
      <span class="btnWidth-x0d6"></span>
      <button keyCode="0x78">F9</button>
      <button keyCode="0x79">F10</button>
      <button keyCode="0x7A">F11</button>
      <button keyCode="0x7B">F12</button>
    </div>
    <!---->
    <div class="key-row">
      <button keyCode="0xC0">~<br/>丶</button>
      <button keyCode="0x31">!<br/>1</button>
      <button keyCode="0x32">@<br/>2</button>
      <button keyCode="0x33">#<br/>3</button>
      <button keyCode="0x34">$<br/>4</button>
      <button keyCode="0x35">%<br/>5</button>
      <button keyCode="0x36">^<br/>6</button>
      <button keyCode="0x37">&<br/>7</button>
      <button keyCode="0x38">*<br/>8</button>
      <button keyCode="0x39">(<br/>9</button>
      <button keyCode="0x30">)<br/>0</button>
      <button keyCode="0x2D">_<br/>-</button>
      <button keyCode="0x3D">+<br/>=</button>
      <button keyCode="0x08" class="btnWidth-x1d5"><div style="transform: scale(2, 1); pointer-events: none;">←</div></button>
      <button keycode="0x7F">Del</button>
    </div>    
    <!---->
    <div class="key-row">
      <button keyCode="0x09" class="btnWidth-x1d5">Tab↹</button>
      <button keyCode="0x51">Q</button>
      <button keyCode="0x57">W</button>
      <button keyCode="0x45">E</button>
      <button keyCode="0x52">R</button>
      <button keyCode="0x54">T</button>
      <button keyCode="0x59">Y</button>
      <button keyCode="0x55">U</button>
      <button keyCode="0x49">I</button>
      <button keyCode="0x4F">O</button>
      <button keyCode="0x50">P</button>
      <button keyCode="0x5B">{<br/>[</button>
      <button keyCode="0x5D">}<br/>]</button>
      <button keyCode="0x5C" class="btnWidth-x1d8">|<br/>\\</button>
    </div>
    <!---->
    <div class="key-row">
      <button keyCode="0x14" updateKeyboardState class="btnWidth-x1d8">CapsⒶ</button>
      <button keyCode="0x41">A</button>
      <button keyCode="0x53">S</button>
      <button keyCode="0x44">D</button>
      <button keyCode="0x46">F</button>
      <button keyCode="0x47">G</button>
      <button keyCode="0x48">H</button>
      <button keyCode="0x4A">J</button>
      <button keyCode="0x4B">K</button>
      <button keyCode="0x4C">L</button>
      <button keyCode="0x3B">:<br/>;</button>
      <button keyCode="0xDE">"<br/>'</button>
      <button keyCode="0x0a" class="btnWidth-x2d6">Enter⏎</button>
    </div>
    <!---->
    <div class="key-row">
      <button keycode="0x10" class="btnWidth-x2d2">Shift</button>
      <button keycode="0x5A">Z</button>
      <button keycode="0x58">X</button>
      <button keycode="0x43">C</button>
      <button keycode="0x56">V</button>
      <button keycode="0x42">B</button>
      <button keycode="0x4E">N</button>
      <button keycode="0x4D">M</button>
      <button keycode="0x2C"><<br/>,</button>
      <button keycode="0x2E">><br/>.</button>
      <button keycode="0x2F">?<br/>/</button>
  
      <span class="btnWidth-x1"></span>
      <button keyCode="0x26">↑</button>
      <span class="btnWidth-x1"></span>
    </div>
    <!---->
    <div class="key-row">
      <button keycode="0x11" class="btnWidth-x1d3">Ctrl</button>
      <button keycode="0x020C" class="btnWidth-x1d3">Win</button>
      <button keycode="0x12" class="btnWidth-x1d3">Alt</button>
      <button keycode="0x20" class="btnWidth-x6d6">_____</button>
      <button keycode="0x020D" class="btnWidth-x1d3">Menu</button>
  
      <span class="btnWidth-x1"></span>
       <!--按住shift时,有问题-->
      <button keyCode="0x25">←</button>
      <button keyCode="0x28">↓</button>
      <button keyCode="0x27">→</button>
    </div>
  </div>
  
  <!--小键盘-->
  <div class="num-board key-bg" style="display: none">
    <button keyCode="0x90" updateKeyboardState>Num</button>
    <button keyCode="0x6F">/</button>
    <button keyCode="0x6A">*</button>
    <button keyCode="0x6D">-</button>
    <!---->
    <button keyCode="0x6B" style="grid-row: 2/4; grid-column: 4;">+</button>
    <button keyCode="0x67">7</button>
    <button keyCode="0x68">8</button>
    <button keyCode="0x69">9</button>
    <!---->
    <button keyCode="0x64">4</button>
    <button keyCode="0x65">5</button>
    <button keyCode="0x66">6</button>
    <!---->
    <button keyCode="0x61">1</button>
    <button keyCode="0x62">2</button>
    <button keyCode="0x63">3</button>
    <button keyCode="0x0a" style="grid-row: 4/6;grid-column: 4;">⏎</button>
    <!---->
    <button keyCode="0x60" style="grid-column: 1/3">0</button>
    <!--按住shift时,不是delete-->
    <button keyCode="SPECIAL:0x6E">.</button>
  </div>

  <!--触摸板-->
  <div id="touchpad" style="display: none; margin-left: 3px">
    <h-touchpad ref="touchpadRef" style="width: 100%; height: 100%;" 
        :on-touchpad-event="onTouchpadEvent" :on-scroll-event="onScrollEvent" 
        :get-rotate-degree="getRotateDegree"/>
  </div>
</div>

<!--设置弹窗: 背景遮罩层, 弹窗内容-->
<div class="simple-dialog" v-show="showSettingDialog">
  <div class="simple-dialog-bg" @click="showSettingDialog=false"></div>
  <div id="setting-dialog-content" class="simple-dialog-content" style="width: initial">
    <div style="padding: 5px 0">
      <span>模式: </span>
      <label><input type="radio" :value="0" v-model="mode">仅键盘</label>
      <label><input type="radio" :value="1" v-model="mode">+小键盘</label>
      <label><input type="radio" :value="2" v-model="mode">+触摸板</label>
    </div>
    <div style="white-space: nowrap;">
      <span>旋转方向</span>
      <label><input type="radio" value="90" v-model="rotateType">90度</label>
      <label><input type="radio" value="-90" v-model="rotateType">-90度</label>
      <span style="margin-left: 20px;" v-text="'当前角度='+rotateDegree"></span>
    </div>
    <div class="bounds-slider">
      <!--
      浏览器问题: 拖拽条的父级 被rotate后, 拖拽条不能拽了
      结论: 
        .开始拽时 必须沿着[原来的横轴方向]拽, 这样就能拖拽了
        .如果是 rotate拖拽条,就不会有此问题
      -->
      <span v-text="'尺寸: '+(diffSize-100)"></span><input type="range" min="0" max="200" v-model="diffSize" @change="saveSetting()">
      <span v-text="'X: '+(diffX-100)"></span><input type="range" min="0" max="200" v-model="diffX" @change="saveSetting()">
      <span v-text="'Y: '+(diffY-100)"></span><input type="range" min="0" max="200" v-model="diffY" @change="saveSetting()">
    </div>
  </div>
</div>

<!--悬浮的设置按钮: 处理(错误或特殊配置造成的)[原按钮]不可见的情况-->
<button id="floating-setting-button" @click="showSetting()">❖</button>
</div>`,
  props: {
    //h-touchpad的入参
    onTouchpadEvent: {
      type: Function,
      default: null,
    },
    onScrollEvent: {
      type: Function,
      default: null,
    }
  },
  data() {
    return {
      // 0-仅左侧键盘,1-右侧是小键盘,2-右侧是触摸板
      mode: storageUtil.getObject('keyboardMode', 0),
      //当前旋转角度,如'90,-90'
      rotateDegree: 0,
      wsConnected: false,
      numOn: false,
      capOn: false,
      scrollOn: false,
      //===
      showSettingDialog: false,
      //用户配置===
      //旋转角度
      rotateType: storageUtil.getObject('keyboardRotateType', '90'),
      //尺寸偏移值
      diffSize: storageUtil.getObject('keyboardDiffSize', 100),
      diffX: storageUtil.getObject('keyboardDiffX', 100),
      diffY: storageUtil.getObject('keyboardDiffY', 100),
    }
  },
  watch: {
    mode(newValue) {
      console.log(`mode=${newValue}, ${typeof newValue}`)
      storageUtil.setStore('keyboardMode', this.mode)
      this.initKeyboardUI()
    },
    rotateType(newValue) {
      storageUtil.setStore('keyboardRotateType', newValue)
      this.initKeyboardUI()
    },
    diffSize() {
      this.initKeyboardUI()
    },
    diffX() {
      this.initKeyboardUI()
    },
    diffY() {
      this.initKeyboardUI()
    },
  },
  mounted() {
    console.log('mounted')
    //插入css
    let cssLink = document.createElement('link');
    cssLink.rel = 'stylesheet';
    cssLink.href = '../component/HKeyboard.css';
    document.head.appendChild(cssLink)

    // this.initKeyboardUI()//mounted时不需要刷新
    window.addEventListener('resize', () => {
      if (browserUtil.isFullScreen()) this.initKeyboardUI();
    })
    window.addEventListener('keydown', e => {
      if (e.keyCode === 122) {
        /*
        122: F11事件
        .屏蔽浏览器[chrome,edge]原有事件
        .因为用户按F11时, 会触发resize事件,但 browserUtil.isFullScreen()总为false
         */
        e.preventDefault()
        browserUtil.switchFullScreen()
      }
    })
  },
  methods: {
    switchMode() {
      this.mode = (this.mode + 1) % 3;
    },
    showSetting() {
      this.showSettingDialog = true
    },
    saveSetting() {
      // console.log('saveSetting')
      storageUtil.setStore('keyboardDiffSize', this.diffSize)
      storageUtil.setStore('keyboardDiffX', this.diffX)
      storageUtil.setStore('keyboardDiffY', this.diffY)
    },
    getRotateDegree() {
      return this.rotateDegree
    },
    /**
     * .自适应[横竖屏,屏幕尺寸]
     * .动态指定[键盘和按钮尺寸,字体大小,不同mode的属性]
     */
    initKeyboardUI() {
      let realWid, realHei//整个键盘的尺寸[主键盘,右侧(数字键盘,触摸板)]
      let rotate
      if (window.innerWidth > window.innerHeight) {
        //横屏
        realWid = window.innerWidth
        realHei = window.innerHeight
        rotate = ``
        this.rotateDegree = 0
      } else {
        //竖屏
        realWid = window.innerHeight
        realHei = window.innerWidth
        rotate = `rotate(${this.rotateType}deg)`
        this.rotateDegree = parseInt(this.rotateType)
      }
      realWid -= 10 // 要减去key-bg的padding, 因为element.style.width=Wid时, 组件实际尺寸是[Wid+两边padding]
      // realHei -= 10 //不用减,因为不用setHeight,计算时要包含padding

      //处理用户配置
      let diffSize = (parseInt(this.diffSize) - 100) / 2
      let diffX = parseInt(this.diffX) - 100
      let diffY = parseInt(this.diffY) - 100
      let transform = `${rotate} translate(${diffX}px, ${diffY}px)`

      /*
      键盘尺寸和布局制定思路
      .固定好按钮布局(很关键)
      .注释js, 直接写死css: 按钮尺寸=38*38,按钮行距=3px, 每行按钮数量=[Tab所在的行]=15
      .键盘四条边的padding都是5px,其中top[5px]=bg[2px]+row[3px]
      .mainBoard总宽度(不含左右padding)=按钮宽*数量+按钮左margin*(数量-1), css最佳效果=38*15+4*14
      .再微调每行的按钮宽度(处理某行的水平padding)

      实际尺寸计算
      .前面得到的css效果是固定尺寸下的, 动态计算时,要微调
      .总宽度=btnWidth*15+margin*14, 其中margin应转成[btnWidth*比例]
      .总高度(含上下padding)=btnWidth*7+margin*8
       */
      let mainBoardWidth = realWid
      if (this.mode !== 0) {
        //比例=(main按钮数量-padding差)/总按钮数量
        mainBoardWidth = Math.floor(mainBoardWidth * 14.9 / 19)
      }
      //计算按钮尺寸
      let columnCount = 15, rowCount = 7
      let btnWidth = Math.floor(mainBoardWidth * 12 / (13 * columnCount - 1))//采用 padding=w/12
      //高度不够时
      let maxBtnHeight = Math.floor(realHei * 12 / (13 * rowCount + 1))
      if (maxBtnHeight < btnWidth) {
        // noinspection JSSuspiciousNameCombination
        btnWidth = maxBtnHeight
      }
      btnWidth += diffSize
      mainBoardWidth = Math.floor(btnWidth * (13 * columnCount - 1) / 12)
      let mainBoardHeight = Math.floor(btnWidth * (13 * rowCount + 1) / 12)
      let fontSize = (btnWidth / 38 * 0.6).toFixed(2)
      let lineHeight = fontSize > 0.5 ? '' : '12px'
      // console.log(`[${window.innerWidth}x${window.innerHeight}], btnWidth=${btnWidth}, mainBoardWidth=${mainBoardWidth}`)

      //keyboard 自适应横竖屏旋转
      document.getElementById('h-keyboard').style.transform = transform

      // mainBoard宽度
      let mainBoard = document.getElementById('main-board')
      mainBoard.style.width = `${mainBoardWidth}px`
      //此处关键!! 解决[竖屏时,键盘旋转后,指定了mainBoard.width],但mainBoard.实际width无效的诡异情况
      mainBoard.style.minWidth = `${mainBoardWidth}px`

      //mainBoard按钮尺寸
      for (let button of mainBoard.getElementsByTagName('button')) {
        button.style.fontSize = `${fontSize}rem`
        button.style.width = `${btnWidth}px`
        button.style.height = `${btnWidth}px`
        button.style.lineHeight = lineHeight
      }

      //查找样式'btnWidth-x' 并计算实际width值, 刷新[按钮,占位span]
      let btnWidthCss = [
        'btnWidth-x0d6', 'btnWidth-x1',
        'btnWidth-x1d3', 'btnWidth-x1d5', 'btnWidth-x1d8',
        'btnWidth-x2', 'btnWidth-x2d2', 'btnWidth-x2d6',
        'btnWidth-x6d6',
      ]
      for (const cssName of btnWidthCss) {
        let ratio = parseFloat(cssName.substring(cssName.indexOf('-x') + 2).replace('d', '.'))
        let targetWidth = Math.floor(btnWidth * ratio)
        // console.log(`style=${cssName}, ratio=${ratio}, targetWidth=${targetWidth}, `)
        for (let element of document.getElementsByClassName(cssName)) {
          element.style.width = `${targetWidth}px`
        }
      }

      //指示灯
      let lamp = document.getElementsByClassName('lamp-board')[0]
      lamp.style.height = `${btnWidth}px`
      lamp.style.fontSize = `${fontSize}rem`
      lamp.style.lineHeight = lineHeight

      //右侧组件
      let numBoard = document.getElementsByClassName('num-board')[0]
      let touchpad = document.getElementById('touchpad')
      if (this.mode === 0) {
        numBoard.style.display = 'none'
        touchpad.style.display = 'none'
      } else if (this.mode === 1) {
        touchpad.style.display = 'none'
        //数字键盘
        numBoard.style.display = 'grid'
        numBoard.style.marginTop = `0px`
        numBoard.style.width = `auto`
        numBoard.style.height = `auto`

        for (let button of numBoard.getElementsByTagName('button')) {
          button.style.fontSize = `${fontSize}rem`
          if (!button.style.gridColumn) {
            button.style.width = `${btnWidth}px`
            button.style.height = `${btnWidth}px`
          } else {
            button.style.width = `auto`
            button.style.height = `auto`
          }
        }
      } else if (this.mode === 2) {
        numBoard.style.display = 'none'
        //触摸板div
        touchpad.style.display = ''
        touchpad.style.width = `${btnWidth * 4 + 15}px`
        touchpad.style.minWidth = touchpad.style.width //解决...
        touchpad.style.height = `${mainBoardHeight + 10}px`
        //触摸板对象
        this.$refs['touchpadRef'].setBaseSize(`${btnWidth}px`, `${fontSize}rem`)
        // console.log('xx', this.$refs['touchpadRef'].setScrollViewSize)
      }

      //设置弹窗
      document.getElementById('setting-dialog-content').style.transform = rotate
      setTimeout(() => {
        /*
        处理设置按钮[看不见,点不到]的情况
        此处用了延时, vue.$nextTick也不能解决[getBoundingClientRect]全是0的问题
         */
        let btnSetting = document.getElementById('btnSetting')
        const rect = btnSetting.getBoundingClientRect()
        // console.log('', rect)
        let canNotTouch = rect.width < 20 || rect.height < 20
          || rect.right < 20
          || rect.left > (window.innerWidth || document.documentElement.clientWidth) - 20
          || rect.bottom < 20
          || rect.top > (window.innerHeight || document.documentElement.clientHeight) - 20

        let btnSettingFloating = document.getElementById('floating-setting-button')
        btnSettingFloating.style.display = canNotTouch ? '' : 'none'
      }, 100)
    },
    //public方法.st=====
    /**
     * 全屏切换时,通知两个触摸板对象,更新配置
     */
    reloadConfig() {
      this.$refs['touchpadRef'].reloadConfig()
    },
    //ws消息=====
    onWsStatusChanged(wsStatus) {
      // console.log('onWsStatusChanged', wsStatus)
      this.wsConnected = wsStatus === WebSocket.OPEN
    },
    /**
     * 键盘灯状态
     */
    onKeyboardState(state) {
      this.numOn = (state & 0x01) !== 0;//0001
      this.capOn = (state & 0x02) !== 0;//0010
      this.scrollOn = (state & 0x04) !== 0;//0100
      // console.log('onKeyboardState', state, this.numOn, this.capOn, this.scrollOn)
    },
    //public方法.ed=====
  },
}
Vue.component('h-keyboard', component)